package com.entertainment.ticketing.controller;

import com.entertainment.ticketing.dto.TicketInfoDTO;
import com.entertainment.ticketing.entity.EventInfo;
import com.entertainment.ticketing.entity.TicketInfo;
import com.entertainment.ticketing.repository.EventInfoRepository;
import com.entertainment.ticketing.repository.TicketInfoRepository;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.http.HttpStatus;

import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/tickets")
public class AdminTicketController {
    private final TicketInfoRepository ticketRepo;
    private final EventInfoRepository eventRepo;

    public AdminTicketController(TicketInfoRepository ticketRepo, EventInfoRepository eventRepo) {
        this.ticketRepo = ticketRepo;
        this.eventRepo = eventRepo;
    }

    @GetMapping
    public ResponseEntity<com.entertainment.ticketing.dto.PageResponse<TicketInfoDTO>> list(
            @RequestParam(value = "page", defaultValue = "0") int page,
            @RequestParam(value = "size", defaultValue = "10") int size,
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam(value = "eventId", required = false) Long eventId,
            @RequestParam(value = "status", required = false) Byte status,
            @RequestParam(value = "sortBy", defaultValue = "createdAt") String sortBy,
            @RequestParam(value = "order", defaultValue = "DESC") String order
    ) {
        int safePage = Math.max(0, page);
        int safeSize = Math.min(Math.max(1, size), 100);
        // 仅允许 createdAt/status/price 三种排序字段
        java.util.List<String> allowedSorts = java.util.List.of("createdAt", "status", "price");
        String safeSortBy = allowedSorts.contains(sortBy) ? sortBy : "createdAt";
        Sort.Direction direction = "ASC".equalsIgnoreCase(order) ? Sort.Direction.ASC : Sort.Direction.DESC;
        Pageable pageable = PageRequest.of(safePage, safeSize, Sort.by(direction, safeSortBy));

        Page<TicketInfo> pageResult;
        Long resolvedEventId = eventId;
        if (resolvedEventId == null && keyword != null && !keyword.isBlank()) {
            try {
                resolvedEventId = Long.valueOf(keyword.trim());
            } catch (NumberFormatException ignored) { }
        }
        String kw = (keyword != null && !keyword.isBlank()) ? keyword.trim() : null;
        pageResult = ticketRepo.searchAdmin(resolvedEventId, status, kw, pageable);

        List<TicketInfoDTO> content = pageResult.getContent().stream().map(this::toDTO).collect(Collectors.toList());
        com.entertainment.ticketing.dto.PageResponse<TicketInfoDTO> resp = new com.entertainment.ticketing.dto.PageResponse<>(
                content,
                pageResult.getNumber(),
                pageResult.getSize(),
                pageResult.getTotalElements(),
                pageResult.getTotalPages(),
                safeSortBy,
                direction.name()
        );
        return ResponseEntity.ok(resp);
    }

    @GetMapping("/{id}")
    public ResponseEntity<TicketInfoDTO> detail(@PathVariable Long id) {
        TicketInfo t = ticketRepo.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "票务不存在"));
        return ResponseEntity.ok(toDTO(t));
    }

    @PostMapping
    public ResponseEntity<TicketInfoDTO> create(@Valid @RequestBody TicketInfoDTO dto) {
        EventInfo event = eventRepo.findById(dto.getEventId()).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "演出不存在"));
        TicketInfo t = new TicketInfo();
        t.setEvent(event);
        t.setTicketType(dto.getTicketType());
        t.setPrice(dto.getPrice());
        t.setSeatArea(dto.getSeatArea());
        t.setSeatRow(dto.getSeatRow());
        t.setSeatNumber(dto.getSeatNumber());
        t.setStatus(dto.getStatus() != null ? dto.getStatus() : 1);
        TicketInfo saved = ticketRepo.save(t);
        return ResponseEntity.ok(toDTO(saved));
    }

    @PutMapping("/{id}")
    public ResponseEntity<TicketInfoDTO> update(@PathVariable Long id, @RequestBody TicketInfoDTO dto) {
        TicketInfo t = ticketRepo.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "票务不存在"));
        if (dto.getEventId() != null) {
            EventInfo event = eventRepo.findById(dto.getEventId()).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "演出不存在"));
            t.setEvent(event);
        }
        if (dto.getTicketType() != null) t.setTicketType(dto.getTicketType());
        if (dto.getPrice() != null) t.setPrice(dto.getPrice());
        if (dto.getSeatArea() != null) t.setSeatArea(dto.getSeatArea());
        if (dto.getSeatRow() != null) t.setSeatRow(dto.getSeatRow());
        if (dto.getSeatNumber() != null) t.setSeatNumber(dto.getSeatNumber());
        if (dto.getStatus() != null) t.setStatus(dto.getStatus());
        TicketInfo saved = ticketRepo.save(t);
        return ResponseEntity.ok(toDTO(saved));
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable Long id) {
        if (!ticketRepo.existsById(id)) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "票务不存在");
        }
        ticketRepo.deleteById(id);
        return ResponseEntity.ok().build();
    }

    private TicketInfoDTO toDTO(TicketInfo t) {
        return TicketInfoDTO.builder()
                .id(t.getId())
                .eventId(t.getEvent().getId())
                .ticketType(t.getTicketType())
                .price(t.getPrice())
                .seatArea(t.getSeatArea())
                .seatRow(t.getSeatRow())
                .seatNumber(t.getSeatNumber())
                .status(t.getStatus())
                .build();
    }
}